package ee.ut.maxorato_macobo.oop.mud.game;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.ListIterator;

import ee.ut.maxorato_macobo.oop.mud.items.ContainsItems;
import ee.ut.maxorato_macobo.oop.mud.items.ItemArmour;
import ee.ut.maxorato_macobo.oop.mud.items.ItemBase;
import ee.ut.maxorato_macobo.oop.mud.items.ItemContainer;
import ee.ut.maxorato_macobo.oop.mud.items.ItemCorpse;
import ee.ut.maxorato_macobo.oop.mud.items.ItemFood;

public class GameCommandSystem {
	private static ArrayList<Class<? extends GameCommand>> commandMap = new ArrayList<Class<? extends GameCommand>>();
	
	public static void registerCommand(Class<? extends GameCommand> commandClass) {
		commandMap.add(commandClass);
	}
	
	public static void loadCommands() {
		registerCommand(CommandWest.class);
		registerCommand(CommandEast.class);
		registerCommand(CommandNorth.class);
		registerCommand(CommandSouth.class);
		registerCommand(CommandEat.class);
		registerCommand(CommandGet.class);
		registerCommand(CommandGo.class);
		registerCommand(CommandGive.class);
		registerCommand(CommandSay.class);
		registerCommand(CommandCast.class);
		registerCommand(CommandDrop.class);
		registerCommand(CommandPut.class);
		registerCommand(CommandLook.class);
		registerCommand(CommandEcho.class);
		registerCommand(CommandRename.class);
		registerCommand(CommandTell.class);
		registerCommand(CommandSlay.class);
		registerCommand(CommandAttack.class);
		registerCommand(CommandAllPlayers.class);
		registerCommand(CommandKill.class);
		registerCommand(CommandExit.class);
		registerCommand(CommandMyId.class);
		registerCommand(CommandMyName.class);
		registerCommand(CommandCmds.class);
		registerCommand(CommandInventory.class);
		registerCommand(CommandInformation.class);
		registerCommand(CommandFlee.class);
		registerCommand(CommandBury.class);
		registerCommand(CommandWear.class);
		registerCommand(CommandEquipment.class);
		registerCommand(CommandStats.class);
		registerCommand(CommandRemove.class);
		registerCommand(CommandSleep.class);
		registerCommand(CommandWake.class);
	}
	
	public static String getCommandName(Class<? extends GameCommand> commandClass) {
		Method cmdNameFunc;
		try {
			cmdNameFunc = commandClass.getDeclaredMethod("getCommandName", (Class[])null);
			return (String)cmdNameFunc.invoke(null, (Object[])null);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	public static Class<? extends GameCommand> findCommandByPrefix(String findName) {
		for(Class<? extends GameCommand> command : commandMap) {
			String cmdName = getCommandName(command);
			
			if(cmdName != null && cmdName.length() >= findName.length() && cmdName.substring(0, findName.length()).equals(findName)) {
				return command;
			}
		}
		
		return null;
	}
	
	public static void processAsCommand(PlayerCharacter player, String text) {
		if(text.trim().length() < 1) {
			player.forcePrompt();
			return;
		}
		
		String[] splitted = text.trim().split(" ", 2);
		
		String commandName = splitted[0].toLowerCase();
		String params = (splitted.length > 1) ? splitted[1] : "";
		
		try {
			if(commandName.length() < 1) throw new Exception();
				
			GameCommand cmd = (GameCommand)findCommandByPrefix(commandName).newInstance();
			cmd.init(player, params);
			player.addCommandToQueue(cmd);
		} catch (Exception e) {
			CommandEcho cmd = new CommandEcho();
			cmd.init(player, "No such command.");
			player.addCommandToQueue(cmd);
		}
	}
	
	public static class GameCommand {
		protected String params;
		protected PlayerCharacter player;
		
		public GameCommand() {
			
		}
		
		public void init(PlayerCharacter newPlayer, String newParams) {
			player = newPlayer;
			params = newParams;
		}
		
		public void execute() {
			
		}
	}
	
	public static class CommandWest extends GameCommand {
		public CommandWest(){}
		public static String getCommandName() { return "west"; }
		
		public void execute() {
			CommandGo cmd = new CommandGo();
			cmd.init(player, "west");
			cmd.execute();
		}
	}
	
	public static class CommandEast extends GameCommand {
		public CommandEast(){}
		public static String getCommandName() { return "east"; }
		
		public void execute() {
			CommandGo cmd = new CommandGo();
			cmd.init(player, "east");
			cmd.execute();
		}
	}
	
	public static class CommandNorth extends GameCommand {
		public CommandNorth(){}
		public static String getCommandName() { return "north"; }
		
		public void execute() {
			CommandGo cmd = new CommandGo();
			cmd.init(player, "north");
			cmd.execute();
		}
	}
	
	public static class CommandSouth extends GameCommand {
		public CommandSouth(){}
		public static String getCommandName() { return "south"; }
		
		public void execute() {
			CommandGo cmd = new CommandGo();
			cmd.init(player, "south");
			cmd.execute();
		}
	}
	
	public static class CommandGo extends GameCommand {
		public CommandGo(){}
		public static String getCommandName() { return "go"; }
		
		public void execute() {
			if(player.getFightTarget() != null) {
				player.sendTickMessage("You cannot move, you are in a fight.");
			}
			else if(player.getIsSleeping()) {
				player.sendTickMessage("You cannot move while you're sleeping.");
			}
			else {
				GameRoom sourceRoom = player.getRoom();
				
				if(sourceRoom != null) {
					GameRoom newRoom = sourceRoom.getExitAtDir(params.trim());
					
					if(newRoom != null) {
						if(player.getEnergy() >= 10) {
							player.setEnergy(player.getEnergy() - 10);
							
							player.moveToRoom(newRoom, params.trim(), true);
						}
						else {
							player.sendTickMessage("You are too tired to move.");
						}
					}
					else {
						player.sendTickMessage("You cannot move in that direction.");
					}
				}
			}
		}
	}
	
	public static class CommandGet extends GameCommand {
		public CommandGet(){}
		public static String getCommandName() { return "get"; }
		
		public void execute() {
			if(player.getIsSleeping()) {
				player.sendTickMessage("You cannot do that while you're sleeping.");
				return;
			}
			
			String[] split = params.split(" ", 2);
			
			if(split.length == 1) {
				ArrayList<ItemBase> findList = GameUtils.getSubListFromArgument(player.getRoom(), 'r', split[0], true);
				boolean isAllArgument = GameUtils.argumentHasAllSpecifier(split[0]);
				
				for(ItemBase item : findList) {
					if(!item.isStatic()) {
						item.moveToLocation(player);
						player.sendTickMessage("You picked up item '" + item.getName() + "'.");
					}
					else {
						if(isAllArgument) player.sendTickMessage(item.getName() + ": that item cannot be moved.");
						else player.sendTickMessage("That item cannot be moved.");
					}
				}
				
				if(findList.size() == 0) {
					player.sendTickMessage("No such items in this room.");
				}
			}
			else if(split.length == 2) {
				ItemBase container = null;
				
				if((container = GameUtils.getSubItemFromArgument(player.getRoom(), 'r', split[1])) != null);
				else if((container = GameUtils.getSubItemFromArgument(player, 'i', split[1])) != null);
				
				if(container == null) {
					player.sendTickMessage("No such container found.");
				}
				else if(!(container instanceof ContainsItems)) {
					player.sendTickMessage("That item is not a container.");
				}
				else {
					ArrayList<ItemBase> foundList = GameUtils.getSubListFromArgument((ContainsItems)container, 'x', split[0], true);
					boolean isAllArgument = GameUtils.argumentHasAllSpecifier(split[0]);
					
					for(ItemBase item : foundList) {
						if(!item.isStatic()) {
							item.moveToLocation(player);
							player.sendTickMessage("You took item '" + item.getName() + "' from container '" + container.getName() + "'.");
						}
						else {
							if(isAllArgument) player.sendTickMessage(GameUtils.stringCapitalize(item.getName()) + ": that item cannot be moved.");
							else player.sendTickMessage("That item cannot be moved.");
						}
					}
					
					if(foundList.size() == 0) {
						player.sendTickMessage("No such items in the container.");
					}
				}
			}
		}
	}
	
	public static class CommandPut extends GameCommand {
		public CommandPut(){}
		public static String getCommandName() { return "put"; }
		
		public void execute() {
			if(player.getIsSleeping()) {
				player.sendTickMessage("You cannot do that while you're sleeping.");
				return;
			}
			
			String[] split = params.split(" ", 2);
			
			if(split.length == 2) {
				ItemBase container = null;
				
				if((container = GameUtils.getSubItemFromArgument(player, 'i', split[1])) != null);
				else if((container = GameUtils.getSubItemFromArgument(player.getRoom(), 'r', split[1])) != null);
				
				if(container == null) {
					player.sendTickMessage("No such container found.");
				}
				else if(!(container instanceof ContainsItems)) {
					player.sendTickMessage("That item is not a container.");
				}
				else {
					ArrayList<ItemBase> foundList = GameUtils.getSubListFromArgument(player, 'i', split[0], true);
					boolean isAllArgument = GameUtils.argumentHasAllSpecifier(split[0]);
					
					for(ItemBase item : foundList) {
						if(item == container) {
							if(isAllArgument) player.sendTickMessage(item.getName() + ": item cannot be put into itself.");
							else player.sendTickMessage("An item cannot be put into itself.");
						}
						else if(!item.isStatic()) {
							String putError = null;
							
							if((putError = ((ContainsItems)container).canAddItem(item)) == null) {
								item.moveToLocation((ContainsItems)container);
								player.sendTickMessage("You put item '" + item.getName() + "' into container '" + container.getName() + "'.");
							}
							else {
								if(isAllArgument) player.sendTickMessage(GameUtils.stringCapitalize(item.getName()) + ": " + putError);
								else player.sendTickMessage(putError);
							}
						}
						else {
							if(isAllArgument) player.sendTickMessage(GameUtils.stringCapitalize(item.getName()) + ": that item cannot be moved.");
							else player.sendTickMessage("That item cannot be moved.");
						}
					}
					
					if(foundList.size() == 0) {
						player.sendTickMessage("No such items in your inventory.");
					}
				}
			}
			else {
				player.sendTickMessage("Invalid number of parameters.");
			}
		}
	}
	
	public static class CommandDrop extends GameCommand {
		public CommandDrop(){}
		public static String getCommandName() { return "drop"; }
		
		public void execute() {
			if(player.getIsSleeping()) {
				player.sendTickMessage("You cannot do that while you're sleeping.");
				return;
			}
			
			ArrayList<ItemBase> foundList = GameUtils.getSubListFromArgument(player, 'i', params, true);
			boolean isAllArgument = GameUtils.argumentHasAllSpecifier(params);
			
			for(ItemBase item : foundList) {
				if(!item.isStatic()) {
					item.moveToLocation(player.getRoom());
					player.sendTickMessage("You dropped item '" + item.getName() + "'.");
				}
				else {
					if(isAllArgument) player.sendTickMessage(GameUtils.stringCapitalize(item.getName()) + ": that item cannot be moved.");
					else player.sendTickMessage("That item cannot be moved.");
				}
			}
			
			if(foundList.size() == 0) {
				player.sendTickMessage("No such items in your inventory.");
			}
		}
	}
	
	public static class CommandGive extends GameCommand {
		public CommandGive(){}
		public static String getCommandName() { return "give"; }
		
		public void execute() {
			if(player.getIsSleeping()) {
				player.sendTickMessage("You cannot do that while you're sleeping.");
				return;
			}
			
			String[] split = params.split(" ", 2);
			
			if(split.length == 2) {
				GameCharacter target = GameUtils.getTargetCharFromArgument(player.getRoom(), split[1]);
				
				if(target == (GameCharacter)player) {
					player.sendTickMessage("You can't give an item to yourself.");
				}
				else if(target != null) {
					if(!GameUtils.argumentHasAllSpecifier(split[0])) {
						ItemBase item = GameUtils.getSubItemFromArgument(player, 'i', split[0]);
						
						if(item != null) {
							if(!item.isStatic()) {
								item.moveToLocation(target);
								
								player.sendTickMessage("You gave " + item.getLongName() + " to " + target.getCharName() + ".");
								
								if(target instanceof PlayerCharacter) {
									((PlayerCharacter)target).sendTickMessage(GameUtils.stringCapitalize(player.getCharName()) + " gave you " + item.getLongName() + ".");
								}
							}
							else {
								player.sendTickMessage("That item cannot be moved.");
							}
						}
						else {
							player.sendTickMessage("No such item in your inventory.");
						}
					}
					else {
						player.sendTickMessage("You can only give one item at a time.");
					}
				}
				else {
					player.sendTickMessage("No such character in this room.");
				}
			}
			else {
				player.sendTickMessage("Give what to who?");
			}
		}
	}
	
	public static class CommandEat extends GameCommand {
		public CommandEat(){}
		public static String getCommandName() { return "eat"; }
		
		public void execute() {
			if(player.getIsSleeping()) {
				player.sendTickMessage("You cannot do that while you're sleeping.");
				return;
			}
			
			ItemBase item = GameUtils.getSubItemFromArgument(player, 'i', params);
			
			if(item != null) {
				if(item instanceof ItemFood) {
					((ItemFood)item).consumedByPlayer(player);
				}
				else {
					player.sendTickMessage("That item is not edible.");
				}
			}
			else {
				player.sendTickMessage("No such item in your inventory.");
			}
		}
	}
	
	public static class CommandLook extends GameCommand {
		public CommandLook(){}
		public static String getCommandName() { return "look"; }
		
		public void execute() {
			if(player.getIsSleeping()) {
				player.sendTickMessage("You look around and see wonderful things, then realize it's just a dream.");
				return;
			}
			
			String[] split = params.trim().split(" ", 2);
			
			if(split.length == 1) {
				if(params.trim().length() > 0) {
					PlayerCharacter findPlayer;
					NpcCharacter findNpc;
					ItemBase findItem;
					
					GameUtils.TypeIndexName findInfo = GameUtils.getArgTypeIndexAndName(params);
					char type = findInfo.type;
					
					if((type == 'x' || type == 'p') && (findPlayer = player.getRoom().findPlayerByName(findInfo.name)) != null) {
						findPlayer.describeForPlayer(player);
					}
					else if((type == 'x' || type == 'n') && (findNpc = player.getRoom().findNpcByName(findInfo.name, findInfo.index)) != null) {
						findNpc.describeForPlayer(player);
					}
					else if((type == 'x' || type == 'r') && (findItem = player.getRoom().findItemByName(findInfo.name, findInfo.index)) != null) {
						findItem.describeForPlayer(player);
					}
					else if((type == 'x' || type == 'i') && (findItem = player.findItemByName(findInfo.name, findInfo.index)) != null) {
						findItem.describeForPlayer(player);
					}
					else {
						if(type == 'p') player.sendTickMessage("No such player in this room.");
						else if(type == 'n') player.sendTickMessage("No such NPC in this room.");
						else if(type == 'r') player.sendTickMessage("No such item in this room.");
						else if(type == 'i') player.sendTickMessage("No such item in your inventory.");
						else player.sendTickMessage("No such entity in here.");
					}
				}
				else {
					player.describeCurrentRoom();
				}
			}
			else if(split.length == 2) {
				ItemBase container = null;
				
				if((container = GameUtils.getSubItemFromArgument(player, 'i', split[1])) != null);
				else if((container = GameUtils.getSubItemFromArgument(player.getRoom(), 'r', split[1])) != null);
				
				if(container == null) {
					player.sendTickMessage("No such container found.");
				}
				else if(!(container instanceof ItemContainer)) {
					player.sendTickMessage("That item is not a container.");
				}
				else {
					ItemBase item = GameUtils.getSubItemFromArgument((ItemContainer)container, 'x', split[0]);
					
					if(item != null) {
						item.describeForPlayer(player);
					}
					else {
						player.sendTickMessage("Container does not have that item.");
					}
				}
			}
			else {
				player.sendTickMessage("Invalid number of parameters");
			}
		}
	}
	
	public static class CommandEcho extends GameCommand {
		public CommandEcho(){}
		public static String getCommandName() { return "echo"; }
		
		public void execute() {
			player.sendTickMessage(params);
		}
	}
	
	public static class CommandRename extends GameCommand {
		public CommandRename(){}
		public static String getCommandName() { return "rename"; }
		
		public void execute() {
			params = params.trim();
			
			if(params.contains(" ") || params.contains("\t")) {
				player.sendTickMessage("Name must not contain whitespace.");
			}
			else if(params.length() < 2) {
				player.sendTickMessage("The length of the name must be at least 2.");
			}
			else if(PlayerPool.getPlayerByName(params) != null) {
				player.sendTickMessage("Name already in use.");
			}
			else {
				player.setPlayerName(params);
				player.sendTickMessage("Name changed to " + player.getPlayerName() + ".");
			}
		}
	}
	
	public static class CommandSay extends GameCommand {
		public CommandSay(){}
		public static String getCommandName() { return "say"; }
		
		public void execute() {
			player.getRoom().tellAll(player, player.getPlayerName() + " says '" + params + "'");
			player.sendTickMessage("You say '" + params + "'");
		}
	}
	
	public static class CommandTell extends GameCommand {
		public CommandTell(){}
		public static String getCommandName() { return "tell"; }
		
		public void execute() {
			String[] sub = params.split(" ", 2);
			
			if(sub.length == 2) {
				PlayerCharacter findPlayer = PlayerPool.getPlayerByName(sub[0]);
				
				if(findPlayer != null) {
					findPlayer.sendTickMessage("Message from " + player.getPlayerName() + ": " + sub[1]);
				}
			}
		}
	}
	
	public static class CommandSlay extends GameCommand {
		public CommandSlay(){}
		public static String getCommandName() { return "slay"; }
		
		public void execute() {
			if(player.getIsSleeping()) {
				player.sendTickMessage("You cannot do that while you're sleeping.");
				return;
			}
			
			GameUtils.TypeIndexName findInfo = GameUtils.getArgTypeIndexAndName(params);
			NpcCharacter findNpc = null;
			
			if((findInfo.type == 'x' || findInfo.type == 'n') && (findNpc = player.getRoom().findNpcByName(findInfo.name, findInfo.index)) != null) {
				findNpc.handleDeath(true);
			}
			else {
				player.sendTickMessage("No such NPC.");
			}
		}
	}
	
	public static class CommandAttack extends GameCommand {
		public CommandAttack(){}
		public static String getCommandName() { return "attack"; }
		
		public void execute() {
			if(player.getIsSleeping()) {
				player.sendTickMessage("You cannot do that while you're sleeping.");
				return;
			}
			
			PlayerCharacter findPlayer;
			NpcCharacter findNpc;
			
			GameUtils.TypeIndexName findInfo = GameUtils.getArgTypeIndexAndName(params);
			char type = findInfo.type;
			
			if((type == 'x' || type == 'p') && (findPlayer = player.getRoom().findPlayerByName(findInfo.name)) != null) {
				player.sendTickMessage("You attacked player " + findPlayer.getCharName() + ".");
				
				player.attackTarget(findPlayer);
			}
			else if((type == 'x' || type == 'n') && (findNpc = player.getRoom().findNpcByName(findInfo.name, findInfo.index)) != null) {
				player.sendTickMessage("You attacked " + findNpc.getCharName() + ".");
				
				player.attackTarget(findNpc);
			}
			else {
				if(type == 'p') player.sendTickMessage("No such player in this room.");
				else if(type == 'n') player.sendTickMessage("No such character in this room.");
				else player.sendTickMessage("No such character in here.");
			}
		}
	}
	
	public static class CommandAllPlayers extends GameCommand {
		public CommandAllPlayers(){}
		public static String getCommandName() { return "allplayers"; }
		
		public void execute() {
			ListIterator<PlayerCharacter> it = PlayerPool.getPlayerList().listIterator();
			
			while(it.hasNext()) {
				PlayerCharacter findPlayer = it.next();
				player.sendTickMessage("Existing player " + findPlayer.getPlayerName() + ", session ID " + findPlayer.getSessionId());
			}
		}
	}
	
	public static class CommandKill extends GameCommand {
		public CommandKill(){}
		public static String getCommandName() { return "kill"; }
		
		public void execute() {
			PlayerCharacter findPlayer = PlayerPool.getPlayerByName(params);
			
			if(findPlayer != null) {
				player.sendTickMessage("Player successfully kicked.");
				findPlayer.sendTickMessage("Player " + player.getPlayerName() + " has kicked you.");
				findPlayer.syncedKickPlayer();
			}
			else {
				player.sendTickMessage("No such player.");
			}
		}
	}
	
	public static class CommandExit extends GameCommand {
		public CommandExit(){}
		public static String getCommandName() { return "exit"; }
		
		public void execute() {
			player.sendTickMessage("Goodbye!");
			player.syncedKickPlayer();
		}
	}
	
	public static class CommandMyId extends GameCommand {
		public CommandMyId(){}
		public static String getCommandName() { return "myid"; }
		
		public void execute() {
			player.sendTickMessage("Your ID is " + player.getSessionId());
		}
	}
	
	public static class CommandMyName extends GameCommand {
		public CommandMyName(){}
		public static String getCommandName() { return "myname"; }
		
		public void execute() {
			player.sendTickMessage("Your name is " + player.getPlayerName());
		}
	}
	
	public static class CommandCmds extends GameCommand {
		public CommandCmds(){}
		public static String getCommandName() { return "cmds"; }
		
		public void execute() {
			String cmdNames = "Commands:";
			
			for(Class<? extends GameCommand> cmd : commandMap) {
				cmdNames += " " + GameCommandSystem.getCommandName(cmd);
			}
			
			player.sendTickMessage(cmdNames);
		}
	}
	
	public static class CommandInventory extends GameCommand {
		public CommandInventory(){}
		public static String getCommandName() { return "inventory"; }
		
		public void execute() {
			player.sendTickMessage("You have the following items in your inventory: ");
			
			GameUtils.describeItemListForPlayer(player, player.getItemList(), false);
		}
	}
	
	public static class CommandInformation extends GameCommand {
		public CommandInformation(){}
		public static String getCommandName() { return "information"; }
		
		public void execute() {
			player.sendTickMessage("Health: " + player.getHealth() + "/" + player.getMaxHealth() + ". Mana: " + player.getMana() + "/" + player.getMaxMana() +
					". Energy: " + player.getEnergy() + "/" + player.getMaxEnergy() + ".");
		}
	}
	
	public static class CommandFlee extends GameCommand {
		public CommandFlee(){}
		public static String getCommandName() { return "flee"; }
		
		public void execute() {
			player.attemptFlee();
		}
	}
	
	public static class CommandBury extends GameCommand {
		public CommandBury(){}
		public static String getCommandName() { return "bury"; }
		
		public void execute() {
			if(player.getIsSleeping()) {
				player.sendTickMessage("You cannot do that while you're sleeping.");
				return;
			}
			
			ItemBase item = null;
			
			if((item = GameUtils.getSubItemFromArgument(player.getRoom(), 'r', params)) != null);
			else if((item = GameUtils.getSubItemFromArgument(player, 'i', params)) != null);
			
			if(item != null) {
				if(item instanceof ItemCorpse) {
					player.sendTickMessage("You buried " + item.getLongName() + ".");
					player.getRoom().tellAll(player, player.getCharName() + " buried " + item.getLongName() + ".");
					
					item.destroyItem();
				}
				else {
					player.sendTickMessage("You cannot bury that item.");
				}
			}
			else {
				player.sendTickMessage("No such item here.");
			}
		}
	}
	
	public static class CommandWear extends GameCommand {
		public CommandWear(){}
		public static String getCommandName() { return "wear"; }
		
		public void execute() {
			if(player.getIsSleeping()) {
				player.sendTickMessage("You cannot do that while you're sleeping.");
				return;
			}
			
			ItemBase item = GameUtils.getSubItemFromArgument(player, 'i', params);
			
			if(item != null) {
				if(item instanceof ItemArmour) {
					if(player.getSlotForArmour((ItemArmour)item) != null) {
						player.sendTickMessage("You put " + item.getLongName() + " on your " + ((ItemArmour)item).getWearLocation() + ".");
						player.wearItem((ItemArmour)item);
					}
					else {
						player.sendTickMessage("No free slot for that equipment.");
					}
				}
				else {
					player.sendTickMessage("That item cannot be worn.");
				}
			}
			else {
				player.sendTickMessage("No such item in your inventory.");
			}
		}
	}
	
	public static class CommandRemove extends GameCommand {
		public CommandRemove(){}
		public static String getCommandName() { return "remove"; }
		
		public void execute() {
			if(player.getIsSleeping()) {
				player.sendTickMessage("You cannot do that while you're sleeping.");
				return;
			}
			
			ArrayList<ItemBase> itemList = GameUtils.getSubListFromArgument(player.equipmentContainer, 'x', params, true);
			
			for(ItemBase item : itemList) {
				player.sendTickMessage("You removed " + item.getLongName() + " from your " + ((ItemArmour)item).getWearLocation() + ".");
				
				item.moveToLocation(player);
			}
			
			if(itemList.size() == 0) {
				player.sendTickMessage("There is no such item on you.");
			}
		}
	}
	
	public static class CommandEquipment extends GameCommand {
		public CommandEquipment(){}
		public static String getCommandName() { return "equipment"; }
		
		public void execute() {
			player.sendTickMessage("You are using:");
			player.describeEquipmentToPlayer(player);
		}
	}
	
	public static class CommandStats extends GameCommand {
		public CommandStats(){}
		public static String getCommandName() { return "stats"; }
		
		public void execute() {
			player.sendTickMessage("Your name is " + player.getPlayerName() + ".");
			player.sendTickMessage("Your defense against pierce attacks is " + player.getDefenseAgainstPierce() + ".");
			player.sendTickMessage("Your defense against bash attacks is " + player.getDefenseAgainstBash() + ".");
			player.sendTickMessage("Your defense against slash attacks is " + player.getDefenseAgainstSlash() + ".");
			player.sendTickMessage("Your defense against magic attacks is " + player.getDefenseAgainstMagic() + ".");
		}
	}
	
	public static class CommandCast extends GameCommand {
		public CommandCast(){}
		public static String getCommandName() { return "cast"; }
		
		public void execute() {
			if(player.getIsSleeping()) {
				player.sendTickMessage("You cannot cast a spell while you're sleeping.");
				return;
			}
			
			GameSpellSystem.processAsSpell(player, params);
		}
	}
	
	public static class CommandSleep extends GameCommand {
		public CommandSleep(){}
		public static String getCommandName() { return "sleep"; }
		
		public void execute() {
			if(player.getFightTarget() != null) {
				player.sendTickMessage("You can't go to sleep when you are fighting.");
			}
			else if(player.getIsSleeping()) {
				player.sendTickMessage("You are already asleep.");
			}
			else {
				player.sendTickMessage("You close your eyes and fall asleep.");
				player.setIsSleeping(true);
			}
		}
	}
	
	public static class CommandWake extends GameCommand {
		public CommandWake(){}
		public static String getCommandName() { return "wake"; }
		
		public void execute() {
			if(!player.getIsSleeping()) {
				player.sendTickMessage("You are not asleep.");
			}
			else {
				player.sendTickMessage("You open your eyes and stand up.");
				player.setIsSleeping(false);
			}
		}
	}
}
